package au.chao.message.listener;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.log4j.Logger;

import au.chao.exception.JIMException;
import au.chao.message.Message;
import au.chao.message.handler.MessageHandler;
import au.chao.message.handler.MessageHandlerFactory;
import au.chao.setting.ServerConfig;
import au.chao.socket.reader.SocketReader;
import au.chao.socket.reader.SocketReaderFactory;
import au.chao.util.DateUtil;
import au.chao.util.SocketUtil;

public class SocketMessageListener implements Listener {
	private static final Logger log = Logger.getLogger(SocketMessageListener.class);
	private int portNumber = ServerConfig.DEFAULT_SERVER_PORT_NUM;

	private ServerSocket mySocket;

	public SocketMessageListener() {
	}

	public SocketMessageListener(int port) {
		portNumber = port;
	}

	public static void main(String[] s) {
		new SocketMessageListener().startListen();
	}

	public void run() {
		while (true) {
			onMessage();
		}
	}

	private void initialize() {
		try {
			mySocket = new ServerSocket(portNumber);
			log.info("Server started at:" + DateUtil.now());
		} catch (IOException e) {
			String error = "Can not start the server";
			log.error(error, e);
			throw new JIMException(error, e);
		}
	}

	@Override
	public void startListen() {
		initialize();
		new Thread(this).start();
	}

	@Override
	public synchronized void onMessage() {
		Socket socket = null;
		SocketReader reader = null;
		try {
			socket = mySocket.accept();
			log.info("Server received request at:" + DateUtil.now());
			reader = SocketReaderFactory.getSocketMessageReader(socket);
			Object receivedObj = reader.readSocket();
			if (receivedObj instanceof Message) {
				MessageHandler msgHandler = MessageHandlerFactory
						.getTextMessageHandler((Message) receivedObj);
				msgHandler.handleMessage();
			} else {
				log.warn("received " + receivedObj + " is not a Message");
			}
		} catch (IOException e) {
			log.error("process connection error", e);
		} finally {
			SocketUtil.closeSocket(socket);
		}
	}
}
